package com.techsoul.module.system.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.techsoul.common.core.exception.BusinessException;
import com.techsoul.common.core.exception.ExcelException;
import com.techsoul.common.core.exception.ParamException;
import com.techsoul.common.core.exception.user.UserException;
import com.techsoul.common.core.pojo.vo.PostVo;
import com.techsoul.common.core.pojo.vo.RoleVo;
import com.techsoul.common.core.util.ServletUtils;
import com.techsoul.common.core.util.bean.BeanUtils;
import com.techsoul.common.core.util.codec.EncodeUtils;
import com.techsoul.common.core.util.collection.ListUtils;
import com.techsoul.common.core.util.http.HttpClientUtils;
import com.techsoul.common.core.util.id.IdWorker;
import com.techsoul.common.core.util.lang.DateUtils;
import com.techsoul.common.core.util.lang.StringUtils;
import com.techsoul.common.core.util.poi.ExcelExport;
import com.techsoul.common.core.util.poi.ExcelImport;
import com.techsoul.common.security.annotation.DataScope;
import com.techsoul.common.security.pojo.LoginUser;
import com.techsoul.common.security.service.TokenService;
import com.techsoul.common.security.util.SecurityUtils;
import com.techsoul.module.system.config.WxpayProperties;
import com.techsoul.module.system.mapper.EmployeeManageMapper;
import com.techsoul.module.system.mapper.UserMapper;
import com.techsoul.module.system.pojo.entity.EmployeeManage;
import com.techsoul.module.system.pojo.entity.User;
import com.techsoul.module.system.pojo.param.*;
import com.techsoul.common.core.pojo.vo.UserVo;
import com.techsoul.module.system.service.*;
import com.techsoul.module.system.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;
import java.util.function.Supplier;

/**
 * 用户 Service实现
 * 
 * @author liuen
 * @date 2020-12-04
 */
@Slf4j
@Service
@Transactional(readOnly = true)
public class UserServiceImpl implements IUserService {

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private WxpayProperties wxpayProperties;

    @Autowired
    private UserMapper mapper;

    @Autowired
    private EmployeeManageMapper employeeManageMapper;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private IRoleService roleService;

    @Autowired
    private IPostService postService;

    @Autowired
    private IUserRoleRelService userRoleRelService;

    @Autowired
    private IUserPostRelService userPostRelService;

    @Autowired
    private IConfigService configService;


 //   @Autowired
  //  private HrEmployeeManageMapper hrEmployeeManageMapper;




    /**
     * 新增
     * @param params
     * @return
     */
    @Transactional(readOnly = false)
    @Override
    public String insert(UserSaveParam params) {
        UserVo user = tokenService.getLoginUser(ServletUtils.getRequest()).getUser();
        // 电话号码加密

        // 新增用户
        User entity = new User();

        BeanUtils.copyProperties(params, entity);
        entity.setPassword(SecurityUtils.encryptPassword("123456"));
        entity.setUserName(params.getPhone());
        entity.setId(idWorker.nextId() + "")
                .preInsert(user.getId());
        if(params.getUserType().equals("平台公司")){
            entity.setSite(params.getOrgId());
        }else if(params.getUserType().equals("供应商")){
            entity.setOrgId("1512956561977380864");
            entity.setSite(params.getSupplierId());

        //    UserRoleRelSaveParam userRoleRelSaveParam = new UserRoleRelSaveParam();
         //   userRoleRelSaveParam.setUserId(entity.getId())
       //             .setRoleId("1512962630963302400");
      //     userRoleRelService.insert(userRoleRelSaveParam);
        }else if(params.getUserType().equals("贸易商")){
            entity.setOrgId("1512956779477209088");
            entity.setSite(params.getCustomerId());

     //       UserRoleRelSaveParam userRoleRelSaveParam = new UserRoleRelSaveParam();
    //        userRoleRelSaveParam.setUserId(entity.getId())
     //               .setRoleId("1512963384033808384");
    //        userRoleRelService.insert(userRoleRelSaveParam);
        }else if(params.getUserType().equals("保理公司")){
            entity.setOrgId("1514185640395280384");
            entity.setSite(params.getBaoliCompanyId());


    //        UserRoleRelSaveParam userRoleRelSaveParam = new UserRoleRelSaveParam();
    //        userRoleRelSaveParam.setUserId(entity.getId())
     //               .setRoleId("1512962180969009152");
     //       userRoleRelService.insert(userRoleRelSaveParam);
        }else{
            entity.setOrgId("1512957013385154560");
            entity.setSite(params.getStoreId());
     //       UserRoleRelSaveParam userRoleRelSaveParam = new UserRoleRelSaveParam();
     //       userRoleRelSaveParam.setUserId(entity.getId())
     //               .setRoleId("1512963088532508672");
     //       userRoleRelService.insert(userRoleRelSaveParam);
        }
        this.mapper.insert(entity);
        // 新增用户角色
        if (ListUtils.isNotEmpty(params.getRoleIds())) {
            for (String roleId : params.getRoleIds()) {
                UserRoleRelSaveParam userRoleRelSaveParam = new UserRoleRelSaveParam();
                userRoleRelSaveParam.setUserId(entity.getId())
                        .setRoleId(roleId);
                userRoleRelService.insert(userRoleRelSaveParam);
            }
        }
        // 新增用户岗位
        if (ListUtils.isNotEmpty(params.getPostIds())) {
            for (String postId : params.getPostIds()) {
                UserPostRelSaveParam userPostRelSaveParam = new UserPostRelSaveParam();
                userPostRelSaveParam.setUserId(entity.getId())
                        .setPostId(postId);
                userPostRelService.insert(userPostRelSaveParam);
            }
        }
        EmployeeManage employeeManage = new EmployeeManage();
        employeeManage.setCurrentJobLoad(0.0);
        employeeManage.setIdCard(entity.getIdCardNo());
        employeeManage.setPersonName(entity.getNickName());
        employeeManage.setStatus("active");
        employeeManage.setUserId(entity.getId());
        employeeManage.setUserType(params.getUserJob());

        employeeManage.setId(idWorker.nextId() + "")
                .preInsert(user.getId());
        this.employeeManageMapper.insert(employeeManage);
        return entity.getId();
    }

    /**
     * 删除
     * @param id
     * @return
     */
    @Transactional(readOnly = false)
    @Override
    public Integer delete(String id) {
        return this.mapper.deleteById(id);
    }

    /**
     * 批量删除
     * @param idList
     */
    @Transactional(readOnly = false)
    @Override
    public Integer batchDelete(List<String> idList) {
        if (ListUtils.isNotEmpty(idList)) {
            return this.mapper.deleteBatchIds(idList);
        } else {
            return 0;
        }
    }

    /**
     * 修改
     * @param params
     * @return
     */
    @Transactional(readOnly = false)
    @Override
    public Integer update(UserSaveParam params) {
        User entityFromDb = this.mapper.selectById(params.getId());
        if (entityFromDb == null) {
            throw new ParamException("id=" + params.getId());
        }
        UserVo user = tokenService.getLoginUser(ServletUtils.getRequest()).getUser();
        BeanUtils.copyProperties(params, entityFromDb);
        entityFromDb.preUpdate(user.getId());
        return this.mapper.updateById(entityFromDb);
    }

    /**
     * 修改角色岗位
     * @param params
     * @return
     */
    @Transactional(readOnly = false)
    @Override
    public void updateRolePost(UserSaveParam params) {
        // 更新用户
        this.update(params);
        // 更新角色，全删全入
        userRoleRelService.deleteByUserId(params.getId());
        if (ListUtils.isNotEmpty(params.getRoleIds())) {
            for (String roleId : params.getRoleIds()) {
                UserRoleRelSaveParam userRoleRelSaveParam = new UserRoleRelSaveParam();
                userRoleRelSaveParam.setUserId(params.getId())
                        .setRoleId(roleId);
                userRoleRelService.insert(userRoleRelSaveParam);
            }
        }
        // 更新岗位，全删全入
        userPostRelService.deleteByUserId(params.getId());
        if (ListUtils.isNotEmpty(params.getPostIds())) {
            for (String postId : params.getPostIds()) {
                UserPostRelSaveParam userPostRelSaveParam = new UserPostRelSaveParam();
                userPostRelSaveParam.setUserId(params.getId())
                        .setPostId(postId);
                userPostRelService.insert(userPostRelSaveParam);
            }
        }
    }

    /**
     * 修改个人信息
     * @param params
     * @return
     */
    @Transactional(readOnly = false)
    @Override
    public Integer updateProfile(UserSaveParam params) {
        Integer count = this.update(params);
        if (count > 0) {
            // 更新缓存用户信息
            LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
            loginUser.getUser().setNickName(params.getNickName());
            loginUser.getUser().setPhone(params.getPhone());
            loginUser.getUser().setEmail(params.getEmail());
            loginUser.getUser().setSex(params.getSex());
            tokenService.setLoginUser(loginUser);
        }
        return count;
    }

    /**
     * 修改密码
     * @param oldPassword
     * @param newPassword
     * @return
     */
    @Transactional(readOnly = false)
    @Override
    public Integer updatePassword(String oldPassword, String newPassword) {
        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
        UserVo user = loginUser.getUser();
        if (!SecurityUtils.matchesPassword(oldPassword, user.getPassword())) {
            throw new UserException("修改密码失败，旧密码错误");
        }
        if (SecurityUtils.matchesPassword(newPassword, user.getPassword())) {
            throw new UserException("新密码不能与旧密码相同");
        }
        UserSaveParam userSaveParam = new UserSaveParam();
        userSaveParam.setId(user.getId())
                .setPassword(SecurityUtils.encryptPassword(newPassword));
        Integer count = this.update(userSaveParam);
        if (count > 0) {
            // 更新登录用户缓存
            loginUser.getUser().setPassword(SecurityUtils.encryptPassword(newPassword));
            tokenService.setLoginUser(loginUser);
        }
        return count;
    }

    /**
     * 重置密码
     * @param id
     * @param password
     * @return
     */
    @Transactional(readOnly = false)
    @Override
    public Integer resetPassword(String id, String password) {
        UserSaveParam userSaveParam = new UserSaveParam();
        userSaveParam.setId(id)
                .setPassword(SecurityUtils.encryptPassword(password));
        return this.update(userSaveParam);
    }

    /**
     * 绑定微信
     * @param params
     */
    @Transactional(readOnly = false)
    public void bindingWeChat(UserWeChatSaveParam params) {
        UserVo user = tokenService.getLoginUser(ServletUtils.getRequest()).getUser();
        // 校验用户code
        if (StringUtils.isEmpty(params.getCode())) {
            log.error("code不能为空");
            throw new BusinessException("code不能为空");
        }
        // 从微信服务器获取openid
        String jscode2sessionStr = "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code";
        String requestUrl = String.format(jscode2sessionStr, wxpayProperties.getAppid(), wxpayProperties.getAppsecret(), params.getCode());
        JSONObject sessionData = JSONObject.parseObject(HttpClientUtils.get(requestUrl));
        if (sessionData == null || StringUtils.isBlank(sessionData.getString("openid"))) {
            log.error("获取用户openid失败");
            throw new BusinessException("获取用户openid失败");
        }
        // 更新用户openid
        UserSaveParam userSaveParam = new UserSaveParam();
        userSaveParam.setId(user.getId())
                .setOpenid(sessionData.get("openid").toString());
        this.update(userSaveParam);
    }

    /**
     * 解绑微信
     * @param id
     */
    public void unBindingWeChat(String id) {
        // 更新用户openid
        UserSaveParam userSaveParam = new UserSaveParam();
        userSaveParam.setId(id)
                .setOpenid("");
        this.update(userSaveParam);
    }

    /**
     * 详情
     * @param id
     * @return
     */
    @Override
    public UserVo findById(String id) {
        UserVo userVo = this.mapper.findById(id);
        if (userVo != null) {
            List<RoleVo> userRoles = roleService.findUserRoles(userVo.getId());
            List<PostVo> userPosts = postService.findUserPosts(userVo.getId());
            userVo.setUserRoles(userRoles)
                    .setUserPosts(userPosts);
        }
        return userVo;
    }

    /**
     * 根据openid查询用户
     * @param openid
     * @return
     */
    @Override
    public UserVo findByOpenid(String openid) {
        UserVo userVo = this.mapper.findByOpenid(openid);
        return userVo;
    }

    /**
     * 根据用户账号查询
     * @param userName
     * @return
     */
    @Override
    public UserVo findByUserName(String userName) {
        UserVo userVo = this.mapper.findByUserName(userName);
        return userVo;
    }

    /**
     * 根据应用ID和密钥查询
     * @param appId
     * @param appSecret
     * @return
     */
    @Override
    public UserVo findByAppIdAndAppSecret(String appId, String appSecret) {
        return this.mapper.findByAppIdAndAppSecret(appId, appSecret);
    }

    /**
     * 列表
     * @param params
     * @return
     */
    @DataScope(userAlias = "t2", orgAlias = "t3")
    @Override
    public List<UserVo> findAll(UserSearchParam params) {
        List<UserVo> users = this.mapper.findAll(params);
        return users;
    }


    /**
     * 列表-分页
     * @param params
     * @param current
     * @param pageSize
     * @return
     */
    @DataScope(userAlias = "t2", orgAlias = "t3")
    @Override
    public IPage<UserVo> findAll(UserSearchParam params, Integer current, Integer pageSize) {
        IPage<UserVo> userPage = this.mapper.findAll(new Page<>(current, pageSize), params);
        List<UserVo> users = userPage.getRecords();
        return userPage;
    }

    /**
     * 列表-角色用户
     * @param roleId
     * @return
     */
    @Override
    public List<UserVo> findRoleUsers(String roleId) {
        List<UserVo> users = this.mapper.findRoleUsers(roleId);
        return users;
    }

    /**
     * 导入模板
     */
    @Override
    public String importTemplate() {
        String baseDir = configService.findByConfigKey("project.attachment.baseDir");
        String baseUrl = configService.findByConfigKey("project.attachment.baseUrl");
        String fileName = "用户导入模板.xlsx";
        try {
            new ExcelExport(null, UserVo.class).writeFile(baseDir + fileName).close();
        } catch (Exception e) {
            log.error("生成用户导入模板失败", e);
            throw new ExcelException(e.getMessage());
        }
        return baseUrl + fileName;
    }

    /**
     * 导入
     * @param file
     * @param isUpdateSupport
     * @return
     */
    @Transactional(readOnly = false)
    @Override
    public String importData(MultipartFile file, boolean isUpdateSupport) {
        String password = configService.findByConfigKey("sys.user.initPassword");
        List<UserVo> dataList = null;
            StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        int successNum = 0;
        int failureNum = 0;
        try {
            ExcelImport excelImport = new ExcelImport(file, 1, 0);
            dataList = excelImport.getDataList(UserVo.class);
        } catch (Exception e) {
            log.error("获取数据信息失败!");
            throw new ExcelException("获取数据信息失败!");
        }
        if (ListUtils.isEmpty(dataList)) {
            throw new ExcelException("导入数据不能为空！");
        }
        for (UserVo data : dataList) {
            try {
                UserSaveParam saveParam = new UserSaveParam();
                BeanUtils.copyProperties(data, saveParam);
                // 验证数据是否存在
                UserVo dataFromDb = this.findByUserName(data.getUserName());
                if (StringUtils.isNull(dataFromDb)) {
                    saveParam.setPassword(SecurityUtils.encryptPassword(password));
                    this.insert(saveParam);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、账号 " + data.getUserName() + " 导入成功");
                } else if (isUpdateSupport) {
                    saveParam.setId(dataFromDb.getId());
                    this.update(saveParam);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、账号 " + data.getUserName() + " 更新成功");
                } else {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、账号 " + data.getUserName() + " 已存在");
                }
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、账号 " + data.getUserName() + " 导入失败：";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ExcelException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }

    @Transactional(readOnly = false)
    @Override
    public  String proveAndConfigWebUser(UserSaveParam params){
        return "success";
    }

    @Transactional(readOnly = false)
    @Override
    public String insertWebUser(UserSaveParam params) {
        // 1. 校验参数
     //   this.verifySaveParam(params, false);
        // 3. 新增用户信息
        User entity = new User();
        org.springframework.beans.BeanUtils.copyProperties(params, entity);
     /*   String loginPassword = PasswordUtils.entryptPassword("123456");
        entity.setLoginPassword(params.getLoginPassword())
                .setId( idWorker.nextId() + "" )
                .preInsert();*/
        // 4. 生成组织机构信息


      /*  entity.setLoginPassword(loginPassword);
        if(!StringUtils.isNull(params.getUserType())){
            if(params.getUserType().equals("PACKSTATION")){
                if(StringUtils.isNull(params.getCustomerId())){
                   String id = this.genCustomer(params);
                    entity.setCustomerId(id);
                    entity.setDepartmentId("CUSTOMER");
                    entity.setOrgIds("SH,CUSTOMER");
                }else{
                    entity.setCustomerId(params.getCustomerId());
                    entity.setDepartmentId("CUSTOMER");
                    entity.setOrgIds("SH,CUSTOMER");
                }
            }else if(params.getUserType().equals("SUPPLIER")){
                if(StringUtils.isNull(params.getSupplierId())){
                    String id = this.genSupplier(params); */
                 /*   entity.setSupplierId(id);
                    entity.setCustomerId(id);
                    entity.setOrgIds("SH,SUPPLIER");
                    entity.setDepartmentId("SUPPLIER");
                }else{
                    entity.setSupplierId(params.getSupplierId());
                    entity.setCustomerId(params.getSupplierId());
                    entity.setDepartmentId("SUPPLIER");
                    entity.setOrgIds("SH,SUPPLIER");
                }
                UserRoleRel userRoleRel = new UserRoleRel();
                userRoleRel.setUserId(entity.getId());
                userRoleRel.setRoleId("1291664999542034432");
                userRoleRel.setId( idWorker.nextId() + "" )
                        .preInsert();
                userRoleRelMapper.insert(userRoleRel);
            }else if(params.getUserType().equals("YAOLINGDANG")){
                User yldcust = this.findByCellNo(params.getMobile());
                if(yldcust!=null){
                    throw new BusinessException(ExceptionEnum.CELL_USED_EXCEPTION);//return "cellUsed";
                }
                entity.setDepartmentId("YAOLINGDANG");
                entity.setOrgIds("SH,YAOLINGDANG");
                String id =this.genYaolingdangCust(params);
                entity.setSupplierId(id);
                entity.setYaolingdangId(id);
            }else if(params.getUserType().equals("CONSIGNEE")){
                if(StringUtils.isNull(params.getConsigneeId())){
                    String id = this.genConsignee(params);
                    entity.setConsigneeId(id);
                    entity.setDepartmentId("CONSIGNEE");
                    entity.setOrgIds("SH,CONSIGNEE");
                }else{
                    entity.setConsigneeId(params.getConsigneeId());
                    entity.setDepartmentId("CONSIGNEE");
                    entity.setOrgIds("SH,CONSIGNEE");
                }
            }
        }
        genOrgInfo(entity);*/
        this.mapper.insert(entity);
        return entity.getId();
    }
    /**
     * 导出
     * @param params
     */
    @Override
    public String exportData(UserSearchParam params) {
        String baseDir = configService.findByConfigKey("project.attachment.baseDir");
        String baseUrl = configService.findByConfigKey("project.attachment.baseUrl");
        String fileName = "用户信息" + DateUtils.getDate("yyyyMMddHHmmss")+".xlsx";
        List<UserVo> list = this.findAll(params);
        try {
            new ExcelExport(null, UserVo.class).setDataList(list).writeFile(baseDir + fileName).close();
        } catch (Exception e) {
            log.error("用户信息导出失败", e);
            throw new ExcelException(e.getMessage());
        }
        return baseUrl + fileName;
    }
}
